package cn.fzkj.framework.aop;

import cn.fzkj.common.utils.ServletUtils;
import cn.fzkj.common.utils.SystemUtils;
import cn.fzkj.framework.annotation.Monitor;
import cn.fzkj.framework.redis.utils.RedisUtil;
import cn.fzkj.project.monitor.domain.SystemLog;
import cn.fzkj.project.monitor.mapper.SystemLogMapper;
import cn.fzkj.project.user.domain.User;
import cn.fzkj.project.user.mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/** 监控系统日志. */
@Aspect
@Component
public class MonitorAspect {
    protected static final Logger log = LoggerFactory.getLogger(MonitorAspect.class);

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SystemLogMapper systemLogMapper;


    @Pointcut("@annotation(cn.fzkj.framework.annotation.Monitor)")
    private void cut(){
    }

    @Around("cut() && @annotation(monitor)")
    public Object around(ProceedingJoinPoint joinPoint, Monitor monitor){
//        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
//        String name = signature.getMethod().getName(); // 拿到请求方式
//        System.out.println("请求方式：" + name);
//        String[] parameterNames = signature.getParameterNames(); // 拿到参数名
//        for (String parameterName : parameterNames) {
//            System.out.println(parameterName);
//        }
//        Object[] args = joinPoint.getArgs();  // 拿到参数值
//        for (Object arg : args) {
//            System.out.println(arg);
//        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        String requestURI = request.getRequestURI(); // 请求路径
        String remoteAddr = request.getRemoteAddr(); // ip
        // 通过ip拿到mac地址
        String mac = SystemUtils.getMacByIP(remoteAddr);
        String remoteHost = request.getRemoteHost();
        String remoteUser = request.getRemoteUser();
        String[] strings = null;
        try {
            strings = SystemUtils.parseUserAgent(ServletUtils.getRequest());
        } catch (Exception e) {
            log.error("找不到请求头中的【user-agent】");
            strings = new String[]{"unkonwn", "unkonwn"}; // 请求头中没有user-agent，自己构造
        }
//        log.error("操作系统信息：{} 浏览器信息：{}", strings[0], strings[1]);
        String realName = null;  // 操作者真实名字
        Integer identity = null; // 操作者身份
        try{
            String token = request.getHeader("token");
            realName = String.valueOf(redisUtil.get(token));
            if (null == realName || "null" == realName || "" == realName)return null;
            QueryWrapper<User> query = new QueryWrapper<>();
            query.eq("user_real_name" , realName);
            User user = userMapper.selectOne(query);
            if (null == user) return null;
            identity = user.getUserType();
            // 将日志保存到数据库.
            SystemLog systemLog = new SystemLog.Builder()
                    .setSysUrl(requestURI)
                    .setSysAddr(remoteAddr)
                    .setSysHost(remoteHost)
                    .setSysRemoteUser(remoteUser)
                    .setSysUserName(realName)
                    .setSysUserType(identity)
                    .setSystemInfo(strings[0])
                    .setBrowserInfo(strings[1])
                    .setSysMac(mac)
                    .build();
            systemLogMapper.insert(systemLog);
            return joinPoint.proceed();
        }catch (Exception e){
            log.error("记录日志时，通过redis查找用户真实姓名抛出异常：{}", e.getMessage());
            return null;
        } catch (Throwable throwable) {
            log.error("joinPoint抛出异常：{}", throwable.getMessage());
            throwable.printStackTrace();
        }
        return null;
    }
}
